home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr48 / 386p_200.zip / TECH.TXT < prev    next >
Text File  |  1995-01-14  |  60KB  |  1,317 lines

  1. 386POWER (sort of) PROGRAMMER GUIDE
  2. -------------------------------------------------------------------------------
  3. Introduction, warnings and credits
  4.  
  5. SMILEY WARNING:
  6.   I use "smileys" (the faces drawn with punctuation marks and other chars
  7.   that you must roll your head to the left to see clearly)
  8.   a lot because i like to write as i talk
  9.   and i heavily use pronunciation inflection.
  10.   (read: the things i say, if they are written as they are,sometimes look like
  11.    an offense or a menace, the smiley correct this).
  12.    ;-) or ;)  == it's a joke, you know i don't mean exactly this.
  13.    :-) or :)  == happy
  14.    :-} or :}  == oops!
  15.    :-(        == i'm not happy of this, will make it better next time
  16.  
  17. PG-A386 WARNING:
  18.   386POWER HAS BEEN RATED Programmer Grade - Assembly 386 !!!!! ;)
  19.   I suppose you know enough of assembly and 386 programming.
  20.  
  21.   If you don't, try the following crash program
  22.   a) Get an access to Internet (direct or by way of a friend)
  23.     (Internet is the big international net i put 386P 2.00
  24.      for public distribution)
  25.   b) Learn how to use the FTP program to get access to the huge resources
  26.      available on the ftp servers connected to Internet.
  27.      If you can, look into the x2ftp.oulu.fi ftp server, it's an ibm pc
  28.      programmer heaven, there, into the /pub/msdos/programming directory
  29.      you can find all the infos and tools you need:
  30.      1) A zipped file containing a complete 386 programming manual
  31.         by Intel (nearly perfect, if you can forgive some typos here and there).
  32.      2) The docs describing VCPI,DPMI and VDS.
  33.      3) The Ralph Brown Interrupt list (lots of info about
  34.         all the function calls you can find working with a pc compatible)
  35.      4) Dos-extenders better than mine :}.
  36.         Just in case you think mine is not good enough, look for pmode305.zip
  37.         You can "attach" it to the basic 386Power
  38.         and get complete DPMI support for most of the ms-dos configuration
  39.         you can find (raw,XMS,VCPI,DPMI).
  40.  
  41. ASM warning:
  42.   This thing is like a shotgun, don't look into its barrel when it's loaded.
  43.   Running under VCPI this baby is capable to tunnel thru the
  44.   protection levels and do nasty things if programmed to do this.
  45.   Be also aware that most of current assemblers perform "automatic"
  46.   code optimizations, i usually test my programs with no optimizations allowed
  47.   so it is easier to find my bugs or the assembler's bugs
  48.   (believe me, assemblers have their own bugs).
  49.  
  50.   I take no responsability for this, this code is not harmfull
  51.   since it is intended mostly for videogames, but intentionally
  52.   or not you can modify it to do very dangerous things.
  53.   Be also aware that even cpus have their bugs and quirks
  54.   so test your program on different cpus if you can.
  55.  
  56. LM WARNING: THIS will scare you ;).
  57.  
  58.   As you can guess from my name and address, i'm italian
  59.   and to say the worse i'm from the northen Italian region called Veneto
  60.   more precisely from a place 40km away from Verona
  61.   (you know, Romeo and Juliet, the Arena)
  62.   here in Veneto there is an old popular motto
  63.   saying "Veronesi tutti matti" (Verona citizens are all crazy)
  64.   and i'm not an exception :).
  65.   This means i think in a very weird way
  66.   (for example: i prefer well documented 386 assembly to C )
  67.   and hate writing documentation like this
  68.   (i prefer putting comments inside the include files ).
  69.   I'm so crazy i'd like to find a job as a game programmer/designer
  70.   (nearly zero probability here in Italy).
  71.   What's more i hate to overtest things, i test them only for what i need
  72.   (don't use this code for an x-ray machine control program
  73.    if you don't like the idea to see people glowing in the dark ;) )
  74.   and i'm never sure to have eradicated all the bugs
  75.   (but i try hard to do this, quality control and bug eradication is planned
  76.    before starting coding).
  77.   If you find some comments or documentation quite hard to understand
  78.   remember some of it has been written while under "berseker coding fury"
  79.   ( picture me typing like a maniac at 00:30 a.m.
  80.     and yelling  "Ah! This code is so neat that explains itself!"
  81.     while the radio volume is set to 'sonic boom' level)
  82.   ( not to mention i haven't lots of freetime).
  83.   And remember that sometimes i write in italo-venetian-english too
  84.   (when i write english things quickly, i keep writing in english using
  85.    phrase structures similar to italian or venetian).
  86.  
  87. Thomas Pytel's PMODE:
  88.  
  89.   I owe lots of thanks to Thomas Pytel for distribuiting the source code
  90.   of his dos-extender.
  91.   Since 386Power is sort of PMODE stepbrother initially i based this
  92.   sort of tech manual on the pmode.doc file included into pmode.zip
  93.   by Thomas "Tran" Pytel, this way it was easier to get the differences
  94.   between the two extenders. Now ... well the dos-extender has grown a lot
  95.   (and degenerated a lot, ulp!)  and tech.txt too.
  96.  
  97.   You might say i mention Tran too many times (or too few times
  98.   if you are Tran ;) ), fact is that i never read a book about 
  99.   386 protected mode programming before starting code this
  100.   (don't get me wrong, i had years of experience programming
  101.   everything from the Z80 to the MC68000)
  102.   but read a lot about other things related to this
  103.   and i already knew real mode assembly programming very well,
  104.   i just looked into tran docs and played with pmode, then i found the 
  105.   DPMI docs  and the Ralph Brown Interrupt List on the internet
  106.   and decided to try to build 386Power.
  107.   What's more i found in the net a complete book in electronic format
  108.   about 386 programming with all the info one may need
  109.   (look in the x2ftp.oulu.fi site).
  110.  
  111.   Anyway, Tran docs together with the pmode sources were the most complete
  112.   thing i found about protected mode programming with some things
  113.   you hardly find in the docs (like how to make VCPI paging work).
  114.   Fact was that Tran coding style was a lot different from mine
  115.   and used self modifying code, PMODE was a wonderful thing
  116.   but wasn't exactly what i wanted, so i restarded from scratch
  117.   keeping and eye on compatibility.
  118.   If you are familiar with the OLD pmode dos-extender
  119.   OR with the old 386power dos-extender, read carefully
  120.   there are some things that are similar but a lot different.
  121.   By the way, as far i know, Tran has produced new and very powerful
  122.   dos-extenders, if you just need a dos-extender, look for the things
  123.   he recently distribuited on the 'net.
  124.  
  125.   If you think the 386Power dos-extender is "not enough" for you
  126.   but you still want to keep the support routines, get a
  127.   dos-extender providing a DPMI interface (like Tran's PMODE 3.05)
  128.   and use 386Power in DPMI mode together with it (but you'll have to
  129.   modify the 386P startup code a little, to set correctly some system vars)
  130.   (by the way, if you choose to do this, you can remove the VCPI stuff
  131.    from 386power.asm and make your program slimmer).
  132.  
  133.  
  134. VERSION WARNING:
  135.   386P is still evolving (look at the XGE driver docs)
  136.   so remember to give a look at the code (AND to the include files)
  137.   if something doesn't work as you expect from the docs.
  138.   
  139. ------------------------------------------------------------------------------
  140. Introduction
  141.  
  142. 386POWER (386P for short ) has been conceived and coded by 
  143. Lorenzo Micheletto (that's me) but is not all "my stuff" (besides mostly is).
  144. It is based on the PMODE dos-extender by Tran (a.k.a. Thomas Pytel)
  145. 386P uses modified algorithms found in the old PMODE 2.24.
  146. I'm not the guy who reinvents the wheel every time (just NEARLY every time ;) ).
  147.  
  148. I wanted to build a GAME ENGINE capable to run under 32bit protected mode.
  149. A game engine is the game equivalent of a data base engine, a set of software
  150. modules you can use as a base to build lots of different games with the
  151. same underlying "animation and sound model".
  152.  
  153. Think about games like Commander Keen 1,2,3,4,5,6 , Duke Nukem 1,2,3,4,5
  154. Bio Menace, Cosmo, etc. etc. They ALL follow the same "model", if they were 
  155. designed using the same set of basic modules handling sound,video and animation
  156. once the first game was build, the other would have needed only different
  157. sound and graphics plus minor game engine updates.
  158. (Well, if you look at Commander K. you will notice 1,2,3 uses the same engine
  159.  and 4,5,6 uses an evolution of the previous engine)
  160.  
  161. From MY point of view (well, i bet somebody has a better point of view)
  162. to build a games engine running in protected mode the following things
  163. were needed:
  164. a) dos-extender module (386Power), to get access to full 32bit power.
  165. b) timekeeping/graphics/text/blitter/game_control_input/sound modules (XGE)
  166. c) finite state automata engine (to program objects motion 
  167.    and "rules of action" of moving object using a table driven 
  168.    automata engine).
  169. < getting here you can easily build a Commander Keen-like game
  170.   or a cool board game like Settlers >
  171.    
  172. d) geometry engine (poligon or bitmap oriented)
  173. < getting here you can build a 3d game >
  174.  
  175. Included with 386P are the XGE modules ( a) and b) ), the other things
  176. are up to you.
  177.  
  178. ------------------------------------------------------------------------------
  179. Why use it?
  180.  
  181. This little thing lets you run a 32bit protected mode program
  182. on nearly any computer with a 386 or better.
  183.  
  184. It can run ...
  185.  
  186.  On MS-DOS with an VCPI/DPMI server (like EMM386, QEMM and others).
  187.  [NO! It won't run on plain real mode, i think it is better to
  188.   run on a trusted "mode switch manager" to smooth out hardware
  189.   differences]
  190.  AND WITH XSM and "raw 386", now!  (but these later modes
  191.  are not that robust in this "forced to be early" release).
  192.  
  193.  In a full-screen MS-Windows dos-box (or dos session) using the DPMI server
  194.  included with MS-Windows  running in 386 enhanced mode
  195.  (see the included *.PIF files to see how to configure a 386powered program
  196.   to run under Windows without "warnings").
  197.  
  198.  In an OS/2 dos-box (maybe this will need a little tweaking of the dos-box
  199.  setup file).
  200.  
  201.  In any other OS with a decent 386+MS-DOS emulator
  202.  (even on risc workstations!!!!).
  203.  
  204. Supporting "only" VCPI and DPMI this baby does not need to run complex
  205. configuration procedures because EMM386 (the ms-dos VPCI server)
  206. is installed by default by the ms-dos install program
  207. and the Windows DPMI server is always present.
  208. I'm also adding XMS and "raw 386" (HARD) support but i'm not happy of this
  209. because i just saw that the some program needs that extra kbyte
  210. that only an XMS or "raw" setup can make available.
  211.  
  212. Running in 32bit (nearly) flat protected mode you will get access to
  213.         a) linear addressable memory up to 4Gbyte
  214.         b) 32bit addressing and data
  215. (this means you will never have to worry about loading segment registers
  216. and other things like that). This means a lot more speed if you understand
  217. the strong points and the weak points of protected mode.
  218.  
  219. ------------------------------------------------------------------------------
  220. ENVIRONMENT INITIALIZATION:
  221.  
  222. 386Power boots from a ms-dos environment (even if emulated)
  223. checks if there is a 32bit (or more) intel compatible CPU (386,486,Pentium,..)
  224. checks if a VCPI or DPMI manager is present
  225. (read: it needs EMM386, QEMM, Windows running in 386 Enhanced Mode
  226.        or OS/2 or at least a VCPI or DPMI server)
  227. checks for XSM or "nothing can help me, i'll have to go 'raw 386' "
  228. and if it finds one it initialize the protected mode environment
  229. for 32bit FLAT PROTECTED mode (one big segment spanning 4Gbyte).
  230.  
  231. Once in Protected Mode IRQs are active and redirected to their
  232. real mode default handlers.
  233.  
  234. ALL "ms-dos interrupt vectors" gets copied to the _OldInt table
  235. (and restored on program termination) so you don't need to save them
  236. and if something goes crazy, there are good changes that the _Exit
  237. routine will be capable to return the system into a "safe" situation.
  238.  
  239. The IRQ mask gets saved, once the program terminates it gets restored
  240. (this should take care of berseker irqs).
  241.  
  242. ------------------------------------------------------------------------------
  243. THE ENVIRONMENT
  244. First of all, the memory layout, as you can guess, is nearly the same of PMODE:
  245.  
  246. Your program will  have at least 3 segments
  247.  
  248. code16   A 16bit segment that holds all the real mode and 16bit protected
  249.          mode init,exit code and real mode irq handlers.
  250.          It has to be the first segment of the EXE.
  251.          
  252. code32   The huge 32bit segment. You can throw in as much code as will fit
  253.          in low memory (no 64k fixup overflows). If you need more code
  254.          space, you're gonna have to load it into extended memory at runtime
  255.          and use it there. 
  256.          Under protected mode, addresses (code and data, they're the
  257.          same memory space) are offset from the beginning of this segment.
  258.          I'll explain later how to access things outside this segment
  259.          if you really need to.
  260.          
  261. codeend  This MUST be the last segment in the EXE. It is the base for the
  262.          stack and low memory allocation.
  263.          If you want to add other segments insert them between
  264.          code32 and codeend
  265.  
  266. The space used by code16+code32+codeend can be as big as the space available
  267. in low memory (the free memory available to plain ms-dos programs)
  268. this usually means between 400k...610k
  269. (it's not a real limit as you will see, because you can put all the data
  270.  into extended memory)
  271.  
  272. two things seems to miss ... 
  273. 1) The STACK...
  274. The stack is shared by your protected mode program AND real mode calls.
  275. This means it can be at most 64k wide (don't worry it's wide enough)
  276. and must be in low memory (where dos code can access it directly).
  277.  
  278. The stack region always begins at codeend, and goes on for STACKSIZE paragraphs.
  279. (a value declared in 386power.inc)
  280. but the stack the main program can use can be at most STACKUSER paragraphs
  281. because the rest is reserved for "temporary stacks"
  282. needed to switch from protected mode to real mode and back (more on this later).
  283.  
  284. 2) The HEAP....
  285.   There are TWO HEAPS you can allocate memory from at run time. 
  286.   
  287. The "Low memory" heap, which covers all conventional memory below A0000h
  288. (the memory accessible to 16bit ms-dos code).
  289.  
  290. The "Extended memory" heap, which covers that big and fat block of memory
  291. above the first megabyte of memory (where only your 386powered program
  292. can go).
  293.  
  294. There's a reason for keeping them separate
  295. (other than that big hole between A0000h and 100000h
  296.  which I did not want to fill in or rearrange with paging):
  297. MS-DOS real mode can only see the low memory heap so low memory is "precious".
  298.  
  299. In calls to ms-dos where you have to pass buffer addresses
  300. you must pass only buffers located in low memory. 
  301. Low memory is the place where you would allocate any critical disk or
  302. DMA buffers (more on this later).
  303.  
  304. ------------------------------------------------------------------------------
  305. VIRTUAL REGISTERS
  306.   You call real mode interrupts and far routines with "virtual registers".
  307. They are memory images of the registers as they will be set for the real mode 
  308. interrupt.  When the mode-switch occours, the current register values 
  309. are pushed into the stack, then the mode switch occours
  310. and the NEW register VALUES are LOADED FROM the virtual registers table.
  311.  
  312. So.. if you set the V86eax variable to 10h
  313. when you switch to real mode, the eax register will contain 10h.
  314. Then when you are back, you can look at the last value of
  315. "eax in real mode" looking into V86eax.
  316.  
  317. ------------------------------------------------------------------------------
  318. Details of runtime:
  319.  
  320. After initialization of the protected mode environment
  321. 386POWER will call a label called _Main located in the code32 segment
  322. (so place _Main: where you want to start your code
  323.  and define it as a PUBLIC variable
  324.  i.e:
  325.                 public _Main
  326.         _Main:
  327.                <insert here your startup code>
  328. )
  329.  
  330. When _Main is reached you can assume that:
  331. 1) The stack is set up and it is STACKUSER*16 bytes wide.
  332. 2) The interrupts are disabled (and have been all the way from real mode)
  333.    just in case there's something you want to do before enabling them.
  334. 3) CS points to the code segment you're running in (code32)
  335.    by way of a selector set up by 386POWER.
  336. 4) DS,ES,FS, and SS point to an alias of the code segment (same memory,
  337.    but write permissions activated) (in protected mode the memory
  338.    referenced thru CS is read-only, so we need another selector
  339.    pointing to the same memory but with  read/write permissions).
  340.   
  341. N.B. Both selectors in 3) and 4) are set with a 4Gigabytes limit
  342.      so you can stuff anything you want into them.
  343.  
  344. 5) GS is a segment that's 4Gigabyte wide but starts at absolute address 0. 
  345.    This is useful for accessing the real mode dos data area, or
  346.    the BIOS data area, or the PSP, etc...
  347.    to access something with real-mode address r_segment:r_offset
  348.    just use gs:(r_offset+(r_segment*16)).
  349.  
  350. 6) ALL interrupt vectors are copied to the _OldInt table
  351.    (they will be restored on interrupt termination)
  352.    so you can change the dos interrupt vectors without having to be worried
  353.    to save 'em.
  354.  
  355. 7) If you run under DPMI
  356.    and you need locked memory (i.e. for IRQ handling) use the DPMI functions
  357.    (check the _386Man var. and call the DPMI lock function if
  358.     _386Man anded with IS_DPMI is different from zero )
  359.    386P tries to lock the memory it allocates, but if the lock fails
  360.    it goes ahead because maybe you don't need it.
  361.     
  362. 8) If you run under VCPI, 386P goes for overkill, because it runs at CPL0
  363.    where no operating system can stop it.
  364.    Man/woman/person/alien warned, half saved, the other half is up to you.
  365.    I usually test my programs under DPMI, then if nothing lethal happens
  366.    i try to see how they work under VCPI (where they run faster
  367.    and have more memory available).
  368.  
  369. 9) If you run under DPMI, an IRQ happened while in "real mode"
  370.    gets reflected to the protected mode handler.
  371.    IF YOU DON'T RUN UNDER DPMI, an irq happened in real mode
  372.    goes to the real mode handler, but 386Power substibutes
  373.    the real mode handler with an "irq reflector" that switches
  374.    control to the protected mode handler and back.
  375.    If an irq is not "redirected", the real mode handler is called
  376.    "directly" (so we can spare two mode switches and go faster).
  377.    There are two exceptions to this rule, IRQ 0 (int 8)
  378.    and IRQ 1 (int 9) are not "automatically reflected"
  379.    (see into 386Power.inc the description of _SetIRQ for more info)
  380.  
  381. Selectors:
  382.  
  383. There are three main selectors you have to know. 
  384. _SelCode, _SelData, and _SelZero are 16bit word vars you can access to get 
  385. the selector values for the code, data, and zero (GS) segments respectively. 
  386.  
  387. When 386power pass control to _Main you can assume
  388. CS=_SelCode, DS=ES=FS=SS=_SelData, and GS=_SelZero. 
  389. You can change the segment register if you wish
  390. (for example to do a REP MOVS in the zero seg). 
  391. But the 386POWER routines and ints expect the segregs to be these values 
  392. And these MUST be the values when you jump to '_Exit' to return to DOS. 
  393. Another thing that is assumed by 386POWER is DF=0 
  394. (direction flag is clear (like the CLD instruction)).
  395. You can perform STD, but before calling 386POWER stuff you have to
  396. "re-set" the direction flag with CLD.
  397.  
  398. Memory layout:
  399.  
  400. Linear address     selector:                    Usage:
  401. 00000000h          _SelZero                    ##  MS-DOS code/data
  402.                                                ##
  403.                                                ##
  404. _Code16Base        <none visible to you>       @@ Your program code starts here
  405.                                                @@ and here you will find
  406.                                                @@ the 16 bit code16 segment
  407.                                                @@ that initializes
  408.                                                @@ your program to prot. mode
  409. _Code32Base        _SelCode,_SelData           || code32 segment starts here
  410.                                                || the lower part of if contains
  411.                                                || the 386P dos extender
  412.                                                || static data and
  413.                                                || 32bit system code
  414.                                                ||
  415.                                                || After that there will be your
  416.                                                || program's code
  417.                                                || and static data
  418.                                                ||
  419.                                                ||
  420.                                                ||
  421.                                                $$ codeend segment
  422.                                                $$ here there will be your stack
  423.                                                $$
  424.                                                $$
  425.                                                $$
  426.                                                $$
  427.                                                LL Here starts the "low" heap
  428.                                                LL
  429.                                                LL
  430.                                                LL
  431.                                                LL
  432.                                                LL
  433.                                                LL
  434.                                                LL
  435.                                                LL
  436.                                                LL
  437.                                                LL
  438.                                                LL
  439. 000A0000h                                      VV Here starts the VGA video
  440.                                                VV memory "address window"
  441.                                                VV
  442.                                                VV
  443. 000C0000h                                      RR Here starts the 384k block
  444.                                                RR used to map EMS pages and
  445.                                                RR UMBs (remapped blocks of ram)
  446.                                                RR where you place the things
  447.                                                RR you "loadhigh"
  448.                                                RR and ROMs
  449.                                                RR
  450.                                                RR
  451.                                                RR
  452.                                                RR
  453.                                                RR
  454.                                                RR
  455. 00100000h                                      XX Extended memory starts here
  456.                                                XX and is usually present other
  457.                                                XX operating system code
  458.                                                XX
  459.                                                XX
  460.                                                XX
  461.                                                .. Here starts the "high" heap
  462.                                                .. (actually extended memory)
  463.                                                .. it is usually more than
  464.                                                .. one megabyte, here you should
  465.                                                .. place all the big chunks
  466.                                                .. of data you need.
  467.                                                ..
  468.                                                ..
  469.                                                ..
  470.                                                ..
  471.                                                ..
  472.  
  473. -------------------------------------------------------------------------------
  474. Linear & relative addresses:
  475.  
  476. All addresses of thing declared in code32 are 
  477. RELATIVE to the beginning of the code32 segment 
  478. (which could start anywhere in low memory). 
  479. nearly all the system code expects addresses that are code32 relative.
  480.  
  481. For this reason, you must adjust any physical memory pointers 
  482. before you use them. 
  483. That is, to access something at linear address A0000h 
  484. (A000:0000, in 16 bit seg:ofs notation) you can use GS 
  485. (it is loaded with the _SelZero selector) and write to GS:0A0000h.
  486.  
  487. If you want to write to A0000h using the default data segment
  488. (because it is faster to do so)
  489. it will not be at DS:A0000, but at 
  490.         DS:(A0000h - linear_address_of_the_beginning_of_Code32).
  491.  
  492. This linear_address_of_the_beginning_of_Code32
  493. is stored in a variable called '_Code32Base'.
  494.  
  495. So if the segment code32 is 1F43, the linear address will be 1F430h 
  496.  
  497. To get a code32-relative pointer to linear address A0000h
  498. you will have to do something like:
  499.  
  500.   mov eax,0A0000h
  501.   sub eax,_Code32Base
  502.   ; now ds:eax points to the same location of linear address 0A0000h
  503.  
  504. To convert the code32-relative offset of MyVar to a linear address
  505. you will have to do something like:
  506.         mov eax,offset MyVar
  507.         add eax,_Code32Base
  508.         ; now gs:eax points to the same location of code32:MyVar
  509.  
  510. The linear address for code16 is also provided in _Code16Base.
  511. As well as the linear address of the PSP in '_PSPBase'.
  512.  
  513. The linear addresses of code16 and PSP will always be less than code32.
  514.  
  515. To access them (memory pointed to by them, these vars are in code32), you will
  516. have to use one of two methods. One is easy enough, just use the GS segment.
  517. Or you could use negative indexes from the normal segment, causing a
  518. 4Gbyte wraparound (a lot like the 64kbyte wraparound under real mode).
  519. However it is rare to access things outside code32, so my advice is to use GS
  520. to make things clear and as a "marker" of things "done outside code32".
  521. Only when you really need speed (i.e. to access the vga memory)
  522. translate the base address once and store it into a variable.
  523.  
  524. Whew! Confused? Look into 386file.asm to see ho this works, it is easier
  525. to see than to explain.
  526.  
  527. -------------------------------------------------------------------------------
  528. THE MEMORY HEAPS: Memory where is my memory?
  529.  
  530. You have two heaps, into low and high (extended) memory.
  531. Each of which is guaranteed to be at least as much as you specified in LOWMIN
  532. and EXTMIN in 386power.inc, the startup code will grab all low memory for you 
  533. (because it's meant to run standalone), and it will attempt 
  534. to grab all the high memory it can. 
  535. Two dword variables hold information about each memory area.
  536.  
  537. _LoMemBase
  538.            and
  539. _LoMemTop
  540.           specify the base and top of the low memory pool as code32-relative
  541.           addresses (ready to use, no adjustment needed).
  542.  
  543. The total amount of low memory available in bytes is _LoMemTop - _LoMemBase 
  544. (notice _LoMemTop points to one byte beyond the last available byte).
  545.  
  546. The _GetLoMem routine is a very simple routine that takes a length in EAX
  547. and checks to see if there is enough low memory. 
  548. If there is enough, it adds the length to _LoMemBase and
  549. returns a pointer (code32 relative, ready to use) in EAX 
  550. to the low memory block along with the carry flag clear.
  551.  
  552. If it finds not enough memory, it returns with the carry flag set. 
  553.  
  554. _HiMemBase, _HiMemTop, and _GetHiMem are the same thing for high memory.
  555.  
  556. Then there is the _GetMem routine that first tries to allocate
  557. low memory and if this fails it tries high memory.
  558.  
  559. -------------------------------------------------------------------------------
  560. Calling real (actually quite virtual) mode:
  561.  
  562. "Real mode" here is used as equivalent to "virtual 8086 mode"
  563. (emulated real mode), when you run under VCPI and DPMI
  564. you cannot get to "true" real mode, but your 16bit "real mode" code
  565. won't notice the difference.
  566.  
  567. You can call real mode, and back. This is only provided so that 
  568. you can call real mode interrupts, and routines that you can't recode 
  569. in protected mode (like the _SetCPUWindows vesa bios function).
  570. Keep these cross-mode calls to the minimum because they eat lots of cpu time
  571. and can raise some nasty "interaction" bugs.
  572.  
  573. You can call real mode interrupts or procedures from protected mode 
  574. through CALL _ExecReal (execute real mode far proc), and
  575. CALL _ExecINT (execute real mode int).
  576.  
  577. These function calls are only available
  578. to the PROTECTED MODE part of your program.
  579.  
  580. To pass register values  from protected mode to real mode  and back 
  581. you use 'virtual registers'.
  582. These 'virtual registers' are merely memory images of EAX,EBX,ECX,EDX,ESI,EDI,
  583. EBP,DS,ES,FS,and GS. AL and AH and AX and BL ... etc ... are there too, and
  584. they share the appropriate memory space with each other so if you change the
  585. 'virtual' AH register, the 'virtual' AX and EAX registers will be changed
  586. accordingly. 
  587. The virtual registers are called V86eax,V86ax,V86ah,V86al and so on...
  588.  
  589. There are no SS,ESP,CS,EIP registers. CS:EIP is taken from the real mode
  590. interrupt vector table (call _ExecINT) or from the processor's CX:DX registers
  591. (call _ExecReal).
  592. SS:ESP is set up by 386POWER together with the extended memory manager
  593. providing protected mode services.
  594.  
  595. @ Call _ExecINT : Do a real mode interrupt.
  596.   AL=interrupt you want to do. All the virtual registers will
  597.   be passed to the real mode handler.
  598.   They will also be passed back as the
  599.   return values into the virtual register table.
  600.   The carry, zero, aux, parity, sign, and overflow flags will
  601.   be passed back as the actual CPU flags. The real mode interrupt will be
  602.   called with interrupts disabled (as it is usually). Keep in mind, no CPU
  603.   registers will be modified (except the flags mentioned). Only their "virtual"
  604.   images will be changed by the real mode int handler.
  605.   REMEMBER that _ExecINT uses the "real mode INT" table found at program start
  606.   (the one copied to the _OldInt table), this looks weird, but it is
  607.   very useful under VCPI when you need "reflected IRQ" service routines.
  608.  
  609. @ Call _ExecReal: Call a real mode far procedure with interrupts disabled.
  610.   CX:DX=seg:off you want to call.
  611.   The register passing works just like _ExecINT.
  612.  
  613. ------------------------------------------------------------------------------
  614. Things to know about IRQs:
  615.  
  616.   Upon startup, all the interrupt vectors for IRQs point to routines that
  617. redirect the IRQs to their default real mode handlers. You can hook into any
  618. IRQ you want. There are two dword pointers that allow you to get and set IRQ
  619. vectors.
  620.  
  621. _GetIRQ and _SetIRQ point to (32bit near) routines to get and set the
  622. relative address of the handler for specific IRQs within the code32 segment.
  623.  
  624. To get the address of a handler, just do a 'call _GetIRQ' with BL set to the
  625. IRQ num you want (0-15). EDX will be returned pointing to its current handler.
  626. To set an IRQ, pass BL again as the IRQ number, and EDX as the offset of the
  627. new handler. You can chain to the old handler if you want just by jumping to
  628. the old address when your handler is done processing.
  629.  
  630. (see specific things about irqs under VCPI
  631.  in the VCPI specific section some pages after this).
  632.  
  633. If you have to enable or disable an IRQ line use the
  634. _GetIRQMask and _SetIRQMask functions, this way your application
  635. will work on anything supported by 386P.
  636.  
  637. Irq handlers in 32bit protected mode are terminated by IRETD.
  638.  
  639. When your IRQ handler is called, you can be sure of ONLY TWO THINGS.
  640. The IF flag is clear and CS is loaded with _SelCode.
  641. All the general regs and segregs should be treated as undefined. 
  642. Even SS cannot be trust, because under DPMI it is set to a little 
  643. "interrupt stack" set up by DPMI. 
  644. In other words ... DON'T CHANGE STACK!!!!
  645. And don't assume SS=DS=CS, if you want access DS, reload it with cs:_SelData
  646. and if you access things using ebp   (i.e. mov eax,[ebp] )
  647. remember SS may not be equal to DS   (so use mov eax,ds:[ebp]).
  648.  
  649.   Another consideration for DPMI is the IF flag. According to DPMI specs, only
  650. CLI, STI, and INT 31h functions AX=900h and AX=901h should be counted on to
  651. modify the interrupt flag (POPF(D) and IRET(D) should not). This is because
  652. certain DPMI systems might have to virtualize the interrupt flag, and keep the
  653. real flag enabled at all times (but don't worry, if the 'virtual' flag is
  654. clear, your program will not get any IRQs). In practice, certain DPMIs do
  655. allow IRET(D)s and POPF(D)s to modify the virtual interrupt flag. But this is
  656. inconsistent across them. So you should follow these rules:
  657.  
  658. @ CLI and STI are allowed, and do their functions.
  659. @ Don't assume anything about POPF(D) and IRET(D) and the interrupt flag.
  660. @ Don't assume the interrupt flag PUSHF(D) stores on the stack is correct,
  661.   it might be the real flag or the 'virtual' flag.
  662. @ These DPMI INT 31h functions are supported under VCPI too
  663.   (by way of the 386POWER interface).
  664.   ) AX=900h: Get state of IF and disable it. Returns AL set to the IF flag.
  665.   ) AX=901h: Get state of IF and enable it. Returns AL set to the IF flag.
  666.   ) AX=902h: Only returns AL set to the IF flag (0=disabled, 1=enabled).
  667. @ At the end of an IRQ handler, put a STI. When the handler is called, flags
  668.   are automatically disabled. 
  669.   If you do not reenable them, and neither does the IRETD... 
  670.   Well... under some systems it will run and on other it will hang.
  671.  
  672. -----------------------------------------------------------------------------
  673. How the stack is shared between modes:
  674.  
  675. 386POWER uses the same stack for both pmode and real mode. This stack is
  676. always located in low memory (always locked under DPMI). 
  677.  
  678. The total size of the stack is set as STACKSIZE in 386power.asm. 
  679. There are other values there called STACKUSER,STACKSWTR & STACKSWTP
  680. that needs further explanations.
  681.  
  682. Your program starts running from the _Main label
  683. with a stack width of STACKUSER paragraphs, so your program can
  684. use up to STACKUSER paragraphs of stack space.
  685.  
  686. When a mode switch occurs FROM PROTECTED MODE TO REAL MODE
  687. the new stack is the old stack base minus STACKSWTR paragraphs. 
  688. (STACKSWTR  == STACK SWitch To Real mode)
  689. This happens when you execute _ExecINT, _ExecReal
  690. or and irq handlers "chains back" to the real mode irq handler.
  691.  
  692. The stack base is the stack location when your program
  693. starts. And it is only modified by mode switches.
  694.  
  695. When a mode switch occurs FROM REAL MODE TO PROTECTED MODE 
  696. the new stack is the old stack base minus STACKSWTP paragraphs. 
  697. (STACKSWTP  == STACK SWitch To Protected mode)
  698. This happens under VCPI when an irq handler gets reflected to prot. mode.
  699.  
  700. When a routine "switches back", the stack it used is destroyed
  701. and the previous stack is selected again.
  702.  
  703. That is, the whole stack structure uses STACKSIZE paragraphs  
  704. but when the program is running it can see only
  705. a "local stack" (let's call it a slot) of variable width
  706. depending on "what is running" (main program or "mode switched stuff").
  707.  
  708. Into each slot you can safely allocate local variables on the stack
  709. referencing them with esp ad ebp without having to worry of mode switches
  710. or reflected irqs triggering a mode switch.
  711. Every time you switch mode, a new slot is used and when you "get back"
  712. to the caller, the caller's slot becomes the current stack again.
  713.  
  714. Let's make an example:
  715.  
  716. Immagine the following "chunks of code"
  717. A is the main program
  718. B is a real mode routine
  719. C is a real mode timer driven interrupt service routine 
  720. D is a protected mode routine
  721.  
  722. To describe the stack status we will use the following notation:
  723.  
  724. XYZ
  725. 123---  a stack structure with six slots and slots 1,2,3 "in use"
  726. MRP     where 3 is the "active stack" and is in use by the Z subroutine
  727.         slot 1 is the "MAIN" slot (STACKUSER wide)
  728.         slot 2 is a "real mode switch" slot (STACKSWTR wide)
  729.         and slot 3 is "prot mode switch" slot (STACKSWTP wide)
  730.        
  731. 1] A is running
  732.  
  733. A
  734. 1-----
  735. M
  736.  
  737. 2] A calls B (mode switch)
  738.                 Now B can switch stack if it wants to
  739.                 but the "current slot" from the point of view of 386P
  740.                 is still SLOT 2
  741. AB
  742. 12----
  743. MR
  744.  
  745. 3] B calls D (mode switch)
  746.          As i said, B may have changed its stack, but the mode-switch code
  747.          doesn't care of this neither has to check what B did
  748.          it just says "well, slot 2 is in use, better get to slot 3".
  749.  
  750. ABD
  751. 123---
  752. MRP
  753.  
  754. 4] routine C triggered by timer interrupt , and the irq handler is in real mode
  755.    (unexpected mode switch you cannot control)
  756.         As usual, another switch happens.
  757.  
  758. ABDC
  759. 1234--
  760. MRPR
  761.  
  762. 5] interrupt handler returns
  763.  
  764. ABD
  765. 123---
  766. MRP
  767.  
  768. 6] D returns
  769.  
  770. AB
  771. 12----
  772. MR
  773.  
  774. 7] B returns
  775.  
  776. A
  777. 1-----
  778. M
  779.  
  780. As you can guess, you'd better keep enough slots available because
  781. if too many mode switch "accumulates" the stack structure will break.
  782.  
  783. 386P up to release 1.01 used only one "slot size", now there are three
  784. slot sizes:
  785. STACKUSER for the main program and the routines in protected mode it calls
  786.           usually i set it to 16..32kbytes
  787. STACKSWTR for every call from protected mode TO real mode.
  788. STACKSWTP for every call from real mode TO protected mode.
  789.           usually is set the "mode switch" stacks to
  790.           1..4kbytes
  791.  
  792. Usually the allocation of STACKSWTR/P slots is caused by IRQ and
  793. "mode switch" calls so these don't use lots of stack space
  794. (256..512 bytes --> 10h .. 20h para) and can be small.
  795.  
  796. Under DPMI things are different but the rule
  797. "the less mode switches, the better" is still true. 
  798. DPMI handles stack switching on its own, any IRQ causes a switch 
  799. to a totally different stack provided by DPMI (argh!).
  800.  
  801. To summarize:
  802. @ In an IRQ handler, DON'T switch off the stack it is entered with. Which is
  803.   not guaranteed that SS=_seldata.
  804.  
  805. @ Don't do too many nested calls across modes.
  806.  
  807. @ You CAN safely assume SS=_seldata in protected mode only in your main stream
  808.   of execution (read: not inside an Interrupt Service Routine)
  809.   
  810. @ Consider your maximum effective stack size to be STACKUSER while
  811.   executing "non mode switched" code.
  812.   
  813. @ You CAN call across modes using INT32/33 from an IRQ handler
  814.   but remember this takes time
  815.   (giving IRQs enough time to stockpile if they "accumulate" fast enough )
  816.   and if you do it the wrong way, the calls get into an infinite loop.
  817.   
  818. @ You'd better handle IRQs from prot mode only and let 386P do
  819.   the nasty irq-reflection work for you.
  820.  
  821. @ If you call ms-dos/bios functions from an IRQ handler, remember most of them
  822.   are NOT reentrant and the actual virtual-machine switches can be different
  823.   from what you expects.
  824.  
  825. @ remember to use IRETD to return control to the main program
  826.   IRET is the "16 bit" interrupt return and you are in 32bit mode.
  827.  
  828. -------------------------------------------------------------------------------
  829. Exception handling:
  830.  
  831. Under DPMI are handled entirely by the DPMI host.
  832.  
  833. Under VCPI, exceptions cause immediate termination
  834. (maybe in future releases i will include some debug messages when
  835.  terminating due to an exception).
  836. ------------------------------------------------------------------------------
  837. Potential DMA and address mapping problems:
  838.  
  839.   As you know, the DMA controllers in the PC use physical addresses.
  840. Nothing but the processor itself knows how linear memory is arranged in the
  841. physical memory banks. When paging is disabled, the relationship is very
  842. simple. The linear address is always the same as the physical address. But
  843. when you enable paging, that could get all screwed up. 
  844. Under VCPI and DPMI paging IS enabled (bad luck, uh?).
  845.  
  846. You can almost definately count on extended memory addresses 
  847. not being consistent with their physical addresses. 
  848. Low memory however, will usually map perfectly to its physical addresses. 
  849. Usually i said, NOT always.
  850.  
  851. The point is that you shouldn't use "raw" DMA under VCPI and DPMI.
  852.  
  853. To handle DMA you should follow the Virtual DMA Specification (VDS).
  854. This is the recommended way of handling DMA under VCPI and DPMI.
  855. See the Ralph Brown interrupt list for INT 4Bh for more info.
  856.  
  857. I've provided a simple VIRTUAL DMA MANAGER [included into 386P]
  858. to handle DMA with or without a Virtual DMA Server.
  859. The current release handles any DMA controller up to ISA bus systems
  860. i plan to add EISA and PCI support (to get faster DMA transferts)
  861. as soon as someone sends me some docs.
  862. Handling "just ISA" means it is not possible to do DMA to/from memory
  863. above the first 16Mbyte (EISA ans PCI can support up to 4Gbyte of addresses).
  864. I hope the current VDS servers included into EMM managers and Windows
  865. can "remap" correctly if you try to do dma above the ISA addressing limit.
  866.  
  867. The main reason to use dma is to make sound, i've included the EXPERIMENTAL
  868. sources of a virtual dma module and chunks of my sound system
  869. "still under devenlopement"
  870. and into the dos-extender there is a function to "map-in"
  871. physical addresses (i still have to test it because to do so
  872. i need a board with ram addresses to map in) (for example: a super vga board
  873. with a "linear mapping" addressing mode like the ET4000)
  874.  
  875. ------------------------------------------------------------------------------
  876. And now to discuss some of the finer points of different protected mode
  877. environments:
  878.  
  879. VCPI:
  880.  
  881. VCPI is nearly "raw" mode. The CPL is 0, and no op-sys routine can trap
  882. into your code if you don't want to.
  883. Paging is enabled, but there is no "virtual memory manager"
  884. (i.e. a thing that can "swap" blocks of memory to/from disk and handle
  885.       sharing of address spaces and other thing like that)
  886. (read: nothing will try to "move your memory" under your feet)
  887. if you want you can mess directly with the page tables (terrific, uh?!?).
  888.  
  889. The problem comes with the way VCPI compatibility works. To call a real mode
  890. interrupt or procedure, we have to pass protected mode control back to the
  891. VCPI server. This comes out to one thing. IRQs that occur in a real mode call
  892. MAY NOT make it to your protected mode handler. It's just the way VCPI works. 
  893. Under VCPI the real mode interrupt table and the protected mode
  894. interrupt table belongs to different Task Segment Descriptors.
  895.  
  896. 386P CAN PLACE an "irq redirector" handler into the real mode task
  897. so if the irq happens in real mode and a "new" irq is installed
  898. in protected mode, the prot mode handler will be called.
  899.  
  900. Well, it looks perfect, isn't it ? Not so perfect, under VPCI and DPMI
  901. there can be MULTIPLE PROTECTED MODE APPLICATIONS RUNNING!!!
  902.  
  903. And the irq redirector works only from the "real mode task" to 
  904. the "386P task" and back, if the IRQ happens while into
  905. another VCPI application you have to hope that "the unknown task"
  906. is a friendly one ( one that reflects to real mode the irqs
  907. it doesn't know how to handle) and what's more, the VCPI/DPMI server
  908. may "look at what's happening" and virtualize things you don't expect
  909. to be virtualized.
  910. Anyway, worry not! This is the worst case scenario.
  911.  
  912. It's all? Not.
  913. There are two other things you have to remember:
  914. a) IRQs needs to be serviced as quickly as you can, or you'll get
  915.    irq overruns and you'll have to send SEOI (specific EOI) codes
  916.    to tame the beast.
  917.    If an irq gets reflected from real to protected mode
  918.    (to let the p. mode handler give a look at it) and then it is
  919.    reflected back to real mode
  920.    (to let the ms-dos irq handler give a look at it too)
  921.    and then you step back where you started ....
  922.    Well, (BAAAAAD!) it takes FOUR mode-switches to go back and forth!!!
  923. b) When you switch, the "mode switch" code does not have to touch
  924.    the hardware that caused the irq.... this is really hard if the
  925.    interrupting device was the keyboard controller
  926.    (that little chip that handles keyboard and other little things
  927.     INCLUDING THE A20 LINE that every mode-switch has to handle).
  928.    So forget to reflect directly to protected mode if the irq was from
  929.    the keyboard controller.
  930.  
  931. To avoid these problems, when you call _SetIRQ under VCPI
  932. the 386Power system code "places" in the real mode interrupt table
  933. a routine that redirects the irq to the protected mode handler
  934. ONLY IF THE IRQ IS NOT one of the "VCPI most wanted" irqs
  935. (IRQ 0 and IRQ1, also known in real mode as INT 8 and INT 9)
  936. If you do want to handle irq 0/1 in real mode too, you can
  937. but you need to set the real mode handler yourself, calling
  938. the ms-dos get/set irq functions by way of _ExecINT.
  939.  
  940. N.B. Look into 386timer.asm how to
  941.      handle directly an irq call in both protected mode and real mode.
  942.  
  943. ANYWAY, when you "restore" the "default" irq handler under protected mode
  944. the 386Power system code AUTOMATICALLY restores the
  945. "default" real mode handler too!!!
  946.  
  947. ------------------------------------------------------------------------------
  948. DPMI:
  949.  
  950.   DPMI is not that bad. 
  951. It could let you select CPL0 for "trusted" applications.
  952. I don't like the overhead imposed by  CPL3 
  953. (in CPL3, certain instructions have to be emulated by software). 
  954. Multitasking virtual machines in general are not that hot 
  955. when you're trying to do a timing critical action game. 
  956.  
  957. One really annoying problem with DPMI is that current implementations are
  958. far from perfect.
  959. QDPMI 1.01 for example, dies when an IRQ occurs in a prot. mode
  960. call from a real mode IRQ. 
  961. DPMI docs say this shouldn't happen, and it doesn't under Windows 3.1 DPMI 
  962. implementation. 
  963. The Windows 3.1 DPMI is a little better but has lethal quirks
  964. that caused me quite big headaches.
  965.  
  966.   Hmm, another little problem is that I'm not sure how many DPMIs out there
  967. actually reflect IRQs to real mode if they occur in protected mode. 
  968. Windows 3.1 seems to send them all over as it should. 
  969. According to Tran QDPMI 1.01 sends IRQ1, but not IRQ0.
  970. And it also doesn't seem to pass IRQs that occur in real mode
  971. through their protected mode handlers, while Windows 3.1 does.
  972.  
  973. Under DPMI, the dpmi server should reflect interrupts for you
  974. (as happens under Win 3.1).
  975.  
  976. ------------------------------------------------------------------------------
  977. XMS / HARD
  978.  
  979. As i said elsewere, these two "nearly raw" (XMS) and "totally raw" (HARD)
  980. "operating modes" are activated when 386P does not detect a
  981. protected mode interface.
  982. This means "linear" memory addresses are equivalent to physical memory
  983. addresses, paging is not active .... AND WE HAVE TO "talk" to hardware
  984. and processor directly.
  985. This also means that every hardware incompatibility cannot be "masked out"
  986. by system software.
  987. there is more extended memory available but there are more possibilities
  988. of error.
  989. There are no exceptions handler (this would require P.I.C. remapping
  990. and may break on "new" computer featuring "improved" P.I.C.)
  991. and if an exception happens this usually means your system hangs up.
  992.  
  993. ------------------------------------------------------------------------------
  994. Some misc notes:
  995.  
  996. @ Under VCPI, 386Power will map as much extended memory as it can, up to
  997. 56M without allowing the page tables to use up more memory than would leave
  998. LOWMIN. Allocating up to 56M means that extended memory under VCPI
  999. can be at most 55M (even if there is more available) plus up to
  1000. 4M of "mapped ram" (ram mapped into the address space from a physical device)
  1001.  
  1002. @ Before exiting your program, you do NOT need to restore any vectors
  1003.   (protected or real mode) nor the typematic rate.
  1004.   And you do not have to restore the IRQ masks at 21h and A1h (PMODE stores
  1005.   them before jumping to _main, and restores them before exiting).
  1006.   BUT if you reprogrammed the irq8/int70h timer interval, set it back to its
  1007.   initial value 
  1008.   (the irq0/int8 is automatically set back to 18.2 Hz by the _Exit routine).
  1009.  
  1010. @ If you're gonna add other 16bit segments, put them in between code32
  1011.   and codeend.
  1012.  
  1013. @ Remember that upon reaching '_Main', interrupts are still disabled. Don't
  1014.   forget to do the STI.
  1015.  
  1016.  
  1017. INTERSEGMENT ACCESS:
  1018.  If you look into 386power.asm you will see that the 16bit initialization code
  1019.  uses the 32bit segment as a data segment, i did it to prevent
  1020.  "automatic grouping" and other "smarts" that current assembler performs
  1021.  that sometime can disrupt what your code is designed to do.
  1022.  Anyway the data accessed by the "little" code16 segment must be the first
  1023.  into the "big" code32 segment so
  1024.  WHEN LINKING, put 386power.obj FIRST on the list of obj files you pass
  1025.  to the linker (this way you are sure the 32bit code in 386power
  1026.  is the nearest to the code16 segment) and check if the segment ordering
  1027.  is SEQUENTIAL (it is possible to turn on alphabetic ordering on some
  1028.  assembler/linkers).
  1029.  
  1030. if you look into 386P remember:
  1031. d16_ means DPMI stuff in code16
  1032. d32_ means DPMI stuff in code32
  1033. v16_ means VCPI stuff in code16
  1034. v32_ means VCPI stuff in code32
  1035. s16_ means "raw" stuff in code16
  1036. s32_ means "raw" stuff in code32
  1037.  
  1038. "raw" == shared between VCPI/DPMI xor "dos-extending" code
  1039.          handle it with care, it bytes!!!
  1040.  
  1041. ------------------------------------------------------------------------------
  1042. Heres a list of other vars provided by PMODE to your program:
  1043.  
  1044. _LoMemBase:dword
  1045.   Low mem base for allocation (first free byte).
  1046.  
  1047. _LoMemTop:dword
  1048.   Top of low mem (last free byte +1).
  1049.  
  1050. _HiMemBase:dword
  1051.   High mem base for allocation (first free byte).
  1052.  
  1053. _HiMemTop:dword
  1054.   Top of high mem (last free byte +1).
  1055.  
  1056. _PSPBase:dword
  1057.   Absolute linear address of start of PSP.
  1058.  
  1059. _Code16Base:dword
  1060.   Absolute linear address of start of code16.
  1061.  
  1062. _Code32Base:dword
  1063.   Absolute linear address of start of code32 (32bit code offset from this).
  1064.  
  1065. _SelCode:word
  1066.   Code segment selector.
  1067.  
  1068. _SelData:word
  1069.   Data segment alias selector for code.
  1070.  
  1071. _SelZero:word
  1072.   Data segment starting at absolute 0.
  1073.  
  1074. _386Man:byte
  1075.   386 manager type:
  1076.      0=VCPI  == program runs in CPL0
  1077.                 real mode irqs are not reflected by default to protected mode.
  1078.                 Paging enabled, but no virtual memory.
  1079.      1=DPMI  == program runs in CPL3
  1080.                 real mode irqs are always reflected to prot. mode
  1081.                 at least the full DPMI 0.9 is available
  1082.                 and you can use the int 31h functions to see if
  1083.                 DPMI 1.0 is present.
  1084.                 Paging enabled, virtual memory enabled (memory pages
  1085.                 may be swapped to/from disk)
  1086.      2=XMS   == program runs in CPL0
  1087.                 Initialization i performed using the XMS functions
  1088.                 then the program "drives the 386" directly.
  1089.                 (still under testing)
  1090.  
  1091.      3=HARD  == Absolutely no extended memory or mode-switch support
  1092.                 from ms-dos, the program runs at CPL0 and has total control.
  1093.                 (still under testing)
  1094.  
  1095. _CPUPower:byte
  1096.         Contains the CPU type detected at initialization:
  1097.         3 = 386
  1098.         4 = 486sx/dx
  1099.         5 = Pentium
  1100.         N.B No checks are done about the FLOATING POINT capabilities!!!!
  1101.  
  1102. _386Return: dword
  1103.    Contains the code32 relative offset to the first message string
  1104.    the _Exit function displays when terminating a 386Power program.
  1105.    The end of the string pointed by _386Return must be marked with '$'
  1106.    because it is written to screen using the dos function int 21h, ah=09h.
  1107.    
  1108. _386Terminator:byte
  1109.    This is the first byte of the standard "termination" program.
  1110.    If you modified _386Return  and want to set it back to the
  1111.    standard message, simply use the following instruction:
  1112.    mov _386Return, offset _386Terminator
  1113.  
  1114. _GetIRQ:dword
  1115.   A pointer to the get IRQ function appropriate for the mode.
  1116.   The function takes arguments as follows:
  1117.     In:
  1118.       BL  == IRQ num (0-0fh)
  1119.     Out:
  1120.       EDX == offset of current IRQ handler
  1121.  
  1122. _SetIRQ:dword
  1123.   A pointer to the set IRQ function.
  1124.   In:
  1125.     BL == bit 0..5: IRQ num (0-15 are the only allowed values)
  1126.           bit 6:  IRQ REFLECTOR STRATEGY
  1127.                   0 = "KILL" REAL MODE IRQ ( only if BIT7 is set and not DPMI)
  1128.                   1 = REFLECT REAL MODE IRQ TO PROT. MODE HANDLER
  1129.                       (only if BIT7 is ser and not DPMI)
  1130.           bit 7:  ACTIVATE CUSTOM IRQ REFLECTOR STRATEGY
  1131.                   0 = Let the extended mode server handle irqs from real mode
  1132.                       as it likes (usually VCPI servers do not reflect irqs)
  1133.                   1 = Enable "direct control" of this irq when it happens
  1134.                       in real mode ( "activate" bit6 )
  1135.     EDX == offset of new IRQ handler to set.
  1136.       
  1137. _OldInt:table of 256 dwords LOCATED IN THE CODE32 SEGMENT
  1138.         It contains all the original real mode int vectors found at
  1139.         386P startup. Instead of storing "old" real mode interrupts yourself
  1140.         386P does it for you.
  1141.  
  1142. ------------------------------------------------------------------------------
  1143. And now some 'functions'. Remember, they ALL need:
  1144.   CS=_SelCode, DS=ES=FS=_Seldata, GS=_SelZero, DF=0 (CLD).
  1145.  
  1146. _GetMem:
  1147.   Allocate any mem, (first checks low, then high)
  1148.   In:
  1149.     EAX == size requested
  1150.   Out:
  1151.     CF=0  memory allocated
  1152.     CF=1  not enough mem
  1153.     EAX == relative pointer to mem or undefined if not enough
  1154.  
  1155. _GetLoMem:
  1156.   Allocate some low mem
  1157.   In:
  1158.     EAX == size requested
  1159.   Out:
  1160.     CF=0  memory allocated
  1161.     CF=1  not enough mem
  1162.     EAX == relative pointer to mem or undefined if not enough
  1163.  
  1164. _GetHiMem:
  1165.   Allocate some high mem
  1166.   In:
  1167.     EAX == size requested
  1168.   Out:
  1169.     CF=0  memory allocated
  1170.     CF=1  not enough mem
  1171.     EAX == linear pointer to mem or undefined if not enough
  1172.  
  1173. _MapPhysmem:
  1174.         Maps into address space a physical memory block of locations
  1175.         used by a physical device.
  1176.         in: eax=physical address base
  1177.             edx=size in bytes
  1178.         out:
  1179.             if CARRY CLEAR then
  1180.                 eax= equivalent code32 relative offset
  1181.             else error, no mapping performed.
  1182.  
  1183.     This function is useful when you need to map
  1184.     into the program's address space the "linear addressable video-ram"
  1185.     provided by some supervga graphics cards.
  1186.     Usually those "memory windows" are enabled by th eprogrammer, so are
  1187.     not visible to the vcpi or dmpi manager, this functions
  1188.     lets you access "new addresses" using the code32 segment.
  1189.     N.B. When running under VCPI the initialization code leaves space
  1190.          for a maximum of 4Mbytes of "new ram"
  1191.          and 56Mbyte of already allocated ram.
  1192.  
  1193. _GetIRQMask:
  1194.   Get status of IRQ mask bit (at port 21h or A1h)
  1195.   In:
  1196.     BL == IRQ num (0-15)
  1197.   Out:
  1198.     AL == status: 0=enabled, 1=disabled
  1199.  
  1200. _SetIRQMask:
  1201.   Set status of IRQ mask bit
  1202.   In:
  1203.     BL == IRQ num (0-15)
  1204.     AL == status: 0=enabled, 1=disabled
  1205.  
  1206. _OnExit:
  1207.   Appends a subroutine BEFORE the current exit code
  1208.   in: EAX= code32 relative offset of routine to call
  1209.   N.B. the "appended" routine must terminate with a RET and preserve
  1210.        all the general porpouse registers EAX..EBP and segment registers
  1211.        and it can only assume CS=_SelCode,DS=_SelData.
  1212.  
  1213. _Exit:
  1214.   Exit to real mode, restore initial IRQ mask
  1215.   restore timer 0 frequency to 18.2 Hz
  1216.   restore ALL interrupt vectors
  1217.   and get out setting video mode 03 (color text 80x25)
  1218.  
  1219. if you really need to deal directly with DMA, check into 386power.inc
  1220. for the "dma support" routines _DMAInit,_DMAInfo,_DMAMap,_DMAUnMap,
  1221. _DMALock,_DMAUnLock,_DMASend,_DMAReceive
  1222.  
  1223. ------------------------------------------------------------------------------
  1224. PROGRAM SUPPORT
  1225.  
  1226. I'm not going to go commercial with 386Power and its companion code.
  1227. Maybe i will go commercial with the games i will produce with it.
  1228. Anyway i will distribuite the sources of this and ALL the future releases
  1229. of 386power and its companion code (the XGE stuff).
  1230.  
  1231. If 386Power doesn't work on your system i'd like to know (so i can fix it) 
  1232. you can reach me at the addresses listed in the end.
  1233. Call me if you have suggestions about new improvements and things like that.
  1234.  
  1235. BUT REMEMBER, 386power is NOT TOTALLY FREE (gosh!)(actually is nearly free)
  1236. See the DISTRIBUTION AGREEMENT LICENSE.DOC  file.
  1237.  
  1238. If you modify 386P (not just cosmetic adjustments of course)
  1239. you should use a different name (to avoid confusion)
  1240. BUT you have to include almost the following message
  1241. "based on the 386Power dos-extender by Lorenzo Micheletto MCHLNZ67T19C890A
  1242.  and on the PMODE dos-extender by Thomas 'Tran' Pytel".
  1243.  
  1244. What's more if you make a commercial thing with it (NOT a commercial
  1245. dos-extender library !!) ... send me a free copy :).
  1246.  
  1247. I won't ask anything more from you.
  1248. It is not a free lunch ... it is a nearly free lunch.
  1249.  
  1250. The main reason i coded 386P was for pure fun and get skilled about
  1251. protected mode programming before coding the real game
  1252. (if i just wanted a dos-extender i would have bought one from FlashTek).
  1253.  
  1254. I distribuite it because: (in priority order)
  1255. a) Needed a wider test base (just my 386 and the 486s' of some friends
  1256.    is a too restricted test base).
  1257. b) I owe it to all the people who distribuited their sources on the net
  1258.    and let me learn how to handle the pc hardware and more.
  1259. c) Need to get a reputation as a programmer, sooner or later
  1260.    when i will try to publish/sell my games, it could be useful.
  1261.    BY THE WAY, 386P 2.00 has to be considered a "partial alpha" release
  1262.    because it wasn't my intention to distribuite it, some people asked me
  1263.    about some routines i included into it, so i decided it was a good thing
  1264.    to send "all the package" instead of a bit here and there.
  1265. ------------------------------------------------------------------------------
  1266.  
  1267. Final things:
  1268.  
  1269. 386Power has been designed with a restricted goal to reach
  1270. (kick my code into 32bit protected mode :} and be sure that on program
  1271. termination no bad things will happen).
  1272. You are free to use it and change it any way you want, but please
  1273. don't make protected mode viruses or trojan horse, i really hate those
  1274. losers that think they are smart because they can destroy things.
  1275. If you think you are smart, design and code a terrific piece of software.
  1276.  
  1277. And as i said, 386P is limited to VCPI and DPMI (if you call it a limit).
  1278. If you want a "real" dos-extender capable to handle anything 
  1279. contact the FlashTek guys and buy it 
  1280. or search the latest pmode release by Tran (Thomas Pytel) on internet
  1281. or get Watcom C++ with the DOS4GW dos-extender
  1282. or anything else you like.
  1283.  
  1284. To reach FlashTek try to ask about them in the rec.games.programmer
  1285. internet newsgroup.
  1286.  
  1287. To find Tran, do the same or ... 
  1288. ....as far i know on may 1993 he could be reached on 
  1289.     Creativity Demo Net or SBCnet as 'Tom Tran'
  1290.     or at the Sound Barrier: (718)979-6629, (718)979-9406
  1291.     or on Internet: tran@phantom.com
  1292.  
  1293.  
  1294. If you want to contact me (for bug reports or other things)
  1295. you can reach me ....
  1296.  
  1297. On the internet as:
  1298. knight@maya.dei.unipd.it
  1299.         (I heard calls from Germany may fail sometimes, if you fail to
  1300.          send e-mail from there, retry two or three times, it is
  1301.          a stocastic bug i think)
  1302.  
  1303. By plain mail at the following address:
  1304.  
  1305. Lorenzo Micheletto 
  1306. Via Piazza Miega 10/A
  1307. Veronella (VERONA)
  1308. ITALY 37040
  1309.  
  1310. N.B. Maybe in 1995 i will be reachable only by plain mail
  1311.      ( i will be in the italian army for a year)
  1312.      but after that (february 1996) i will sure be back to Padova
  1313.      WITH A "FULL POWER" 386P 3.00 release that hopefully
  1314.      take care of all the incomplete things in release 2.00
  1315.      and will give you all you need to make game engines.
  1316.      
  1317.